package com.ldr.custom.spring.v3.aop;

import com.ldr.custom.spring.v3.aop.intercept.GPReflectiveMethodInvocation;
import com.ldr.custom.spring.v3.aop.support.GPAdvisedSupport;
import sun.misc.ProxyGenerator;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * 代理对象
 * 默认用jdk动态代理
 */
public class GPJdkDynamicAopProxy implements InvocationHandler, GPAopProxy {

    private GPAdvisedSupport advised;

//    private Object target;

    //存储aop配置
    public GPJdkDynamicAopProxy(GPAdvisedSupport config) {
        this.advised = config;
    }

//    public void setConfig(GPAdvisedSupport config) {
//        this.advised=config;
//    }

    //把原生对象传进来
//    public Object getProxy(Object instance) {
//        this.target = instance;
//        Class<?> clazz = instance.getClass();
//        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
//    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //method是接口方法，proxy原生代理对象
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, this.advised.getTargetClass());

        GPReflectiveMethodInvocation invocation = new GPReflectiveMethodInvocation(proxy, this.advised.getTargetSource(), method, args, this.advised.getTargetClass(), chain);
        //执行调用链方法
        return invocation.proceed();
    }

    @Override
    public Object getProxy() {
        return getProxy(this.advised.getTargetClass().getClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        //生成代理类到磁盘
        //        writeClassToDisk("/Users/lidarong/Downloads/图片/$Proxy4.class");
        return Proxy.newProxyInstance(classLoader, this.advised.getTargetClass().getInterfaces(), this);
    }

    public void writeClassToDisk(String path){

        byte[] classFile = ProxyGenerator.generateProxyClass("$proxy4", new Class<?>[]{advised.getTargetClass().getInterfaces()[0]});
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(path);
            fos.write(classFile);
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
